home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / network.zip / SOURCE.ZIP / POSTMAN.C < prev    next >
C/C++ Source or Header  |  1990-01-01  |  33KB  |  1,222 lines

  1. /*      E-Mail  V1.00   (PostMan)              */ 
  2. /*      Copyright (c) 1989 Barry R. Nance      */
  3.  
  4. #pragma  inline
  5.  
  6. #include <stdio.h>
  7. #include <dos.h>
  8. #include <dir.h>
  9. #include <mem.h>
  10. #include <io.h>
  11. #include <fcntl.h>
  12. #include <errno.h>
  13. #include <conio.h>
  14. #include <bios.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <stddef.h>
  18. #include <stdarg.h>
  19. #include <time.h>
  20. #include <netbios.h>
  21.  
  22. void    send_mail(int first_item);
  23. void    interrupt POST_routine(void);
  24. void    process_mail(void);
  25. int     fgetbuf(int fh);
  26. int     fgetstring(int fh, char buff[], int max_chars);
  27. void    beep(void);
  28.  
  29. #define TRUE         1
  30. #define FALSE        0
  31. #define LINEFEED    10
  32. #define CR          13
  33.  
  34. #define ACK          1
  35. #define HEADER      10
  36. #define MAIL_DATA   20
  37. #define MAIL_EOF    30
  38. #define FILE_HDR    50
  39. #define FILE_DATA   60
  40. #define FILE_EOF    70
  41. #define TRAILER     99
  42.  
  43. NCB     cancel_ncb;
  44. NCB     add_name_ncb;
  45. NCB     delete_name_ncb;
  46. NCB     send_dg_ncb;
  47. NCB     receive_dg_ncb;
  48. NCB     temp_ncb;
  49.  
  50. void interrupt  (*int_5C_vector)(void);
  51.  
  52. char    machine_name[16];
  53. char    mail_name[16];
  54. char    caller[16];
  55. char    addressee[16];
  56. char    subject[31];
  57. unsigned char name_number;
  58.  
  59. typedef struct
  60.         {
  61.         char    type;
  62.         int     sequence;
  63.         int     data_length;
  64.         char    data[500];
  65.         } MAIL_PACKET;
  66.  
  67. MAIL_PACKET packet_in;
  68. MAIL_PACKET packet_out;
  69.  
  70. typedef struct
  71.         {
  72.         char    addressee[16];
  73.         char    to_name[16];
  74.         char    sender[16];
  75.         char    maildate[17];
  76.         char    subject[31];
  77.         char    copy_flag;
  78.         char    attachment_flag;
  79.         char    attachment_name[66];
  80.         char    cc_list[66];
  81.         char    read_flag;
  82.         char    crlf[2];
  83.         } ENVELOPE;
  84.  
  85. ENVELOPE    envelope_in;
  86. ENVELOPE    envelope_out;
  87.  
  88. int     errors_this_packet = 0;
  89. int     send_handle = -1;
  90. int     mail_handle = -1;
  91. int     file_handle = -1;
  92. int     expected_sequence = 1;
  93. char    state = 0;
  94.  
  95. unsigned    paragraphs;
  96. char        critical_error = FALSE;
  97. int         i, j, k;
  98. unsigned    temp1, temp2;
  99. unsigned    temp_ax;
  100. unsigned char temp_ah;
  101. unsigned    old_ss, old_sp, our_ss, our_sp;
  102. char        far *ourdta_ptr;
  103. char        far *olddta_ptr;
  104. char        far *our_mcb;
  105. unsigned    far *our_mcb_size;
  106. char        far *next_mcb;
  107. unsigned    far *next_mcb_owner;
  108. unsigned    ourpsp;
  109. unsigned    oldpsp;
  110. int         break_state;
  111. void     interrupt (*oldint08)(void);
  112. void     interrupt (*oldint09)(void);
  113. void     interrupt (*oldint10)(void);
  114. void     interrupt (*oldint13)(void);
  115. void     interrupt (*oldint16)(void);
  116. void     interrupt (*oldint1b)(void);
  117. void     interrupt (*oldint1c)(void);
  118. void     interrupt (*oldint23)(void);
  119. void     interrupt (*oldint24)(void);
  120. void     interrupt (*oldint28)(void);
  121. char far             *kbd_flag_ptr;
  122. unsigned char far    *indos_ptr;
  123. unsigned char far    *indos2_ptr;
  124. unsigned char    in_int08 = FALSE;
  125. unsigned char    in_int09 = FALSE;
  126. unsigned char    in_int10 = FALSE;
  127. unsigned char    in_int13 = FALSE;
  128. unsigned char    in_int16 = FALSE;
  129. unsigned char    in_int28 = FALSE;
  130. unsigned char    in_popup = FALSE;
  131. unsigned char    de_install = FALSE;
  132. unsigned char    mail_flag = FALSE;
  133. unsigned char    new_mail  = FALSE;
  134. unsigned char    incoming_msg = FALSE;
  135. unsigned char    break_flag = FALSE;
  136.  
  137. unsigned char    trigger_outbasket= FALSE;
  138. unsigned char    incoming_timeout = FALSE;
  139. unsigned char    no_answer        = FALSE;
  140.  
  141. unsigned char   first_packet = FALSE;
  142. long            tick_counter = 0l;
  143.  
  144. long            outbasket_alarm = 10920l;
  145. long            incoming_alarm  = 0x0FFFFFFFl;
  146. long            no_answer_alarm = 0x0FFFFFFFl;
  147.  
  148. char            mail_path[65];
  149. char            io_buffer[512];
  150. char            outname[81];
  151. char            mailname[81];
  152. char            filename[81];
  153. char            string[101];
  154.  
  155. struct ffblk    find_block;
  156. int             io_len    = 0;
  157. unsigned int    fbufndx   = 2000;
  158. unsigned int    fbufbytes = 0;
  159. unsigned        *our_stack;
  160.  
  161. /* - - - - - - - - - - - - - - - - - - - - - - - - */
  162.  
  163. void    interrupt int08(void)
  164.     {
  165.     in_int08 = TRUE;
  166.     oldint08();
  167.     tick_counter++;
  168.     enable();
  169.  
  170.     if (tick_counter > outbasket_alarm)
  171.         {
  172.         mail_flag = TRUE;
  173.         trigger_outbasket = TRUE;
  174.         }
  175.  
  176.     if (tick_counter > incoming_alarm)
  177.         {
  178.         mail_flag = TRUE;
  179.         incoming_timeout = TRUE;
  180.         }
  181.  
  182.     if (tick_counter > no_answer_alarm)
  183.         {
  184.         mail_flag = TRUE;
  185.         no_answer = TRUE;
  186.         }
  187.  
  188.     if (!de_install && !mail_flag)
  189.         goto exit08;
  190.  
  191.     if (in_popup)
  192.         goto exit08;
  193.  
  194.     if (in_int09 || in_int10 || in_int13 || in_int16 || in_int28)
  195.         goto exit08;
  196.  
  197.     if (*indos_ptr != 0)
  198.          goto exit08;
  199.  
  200.     if (*indos2_ptr != 0)
  201.          goto exit08;
  202.  
  203.     outportb(0x20, 0x0b);
  204.     if (inportb(0x20)) goto exit08;
  205.  
  206.     in_popup = TRUE;
  207.     process_mail();
  208.     in_popup = FALSE;
  209.  
  210. exit08:
  211.     in_int08 = FALSE;
  212.     }
  213.  
  214. void interrupt  int09 (void)
  215.     {
  216.     in_int09 = TRUE;
  217.     oldint09();
  218.     enable();
  219.     in_int09 = FALSE;
  220.     }
  221.  
  222. void    far int10(unsigned flags)
  223.     {
  224.     asm     pop  bp
  225.  
  226.     asm     push ax
  227.     asm     push ds
  228.     asm     mov  ax, DGROUP
  229.     asm     mov  ds, ax
  230.     asm     mov  _in_int10, 1
  231.     asm     pop  ds
  232.     asm     pop  ax
  233.  
  234.     asm     pushf
  235.     asm     call    dword ptr cs:[0000h]
  236.     asm     sti
  237.  
  238.     asm     push bp
  239.     asm     mov  bp, sp
  240.     asm     pushf
  241.     asm     pop  flags
  242.     asm     pop  bp
  243.  
  244.     asm     push ax
  245.     asm     push ds
  246.     asm     mov  ax, DGROUP
  247.     asm     mov  ds, ax
  248.     asm     mov  _in_int10, 0
  249.     asm     pop  ds
  250.     asm     pop  ax
  251.  
  252.     asm     iret
  253.     }
  254.  
  255. void    far int13(unsigned flags)
  256.     {
  257.     asm     pop  bp
  258.  
  259.     asm     push ax
  260.     asm     push ds
  261.     asm     mov  ax, DGROUP
  262.     asm     mov  ds, ax
  263.     asm     mov  _in_int13, 1
  264.     asm     pop  ds
  265.     asm     pop  ax
  266.  
  267.     asm     pushf
  268.     asm     call    dword ptr cs:[0004h]
  269.     asm     sti
  270.  
  271.     asm     push bp
  272.     asm     mov  bp, sp
  273.     asm     pushf
  274.     asm     pop  flags
  275.     asm     pop  bp
  276.  
  277.     asm     push ax
  278.     asm     push ds
  279.     asm     mov  ax, DGROUP
  280.     asm     mov  ds, ax
  281.     asm     mov  _in_int13, 0
  282.     asm     pop  ds
  283.     asm     pop  ax
  284.  
  285.     asm     iret
  286.     }
  287.  
  288. void    interrupt int16(unsigned bp,
  289.                         unsigned di,
  290.                         unsigned si,
  291.                         unsigned ds,
  292.                         unsigned es,
  293.                         unsigned dx,
  294.                         unsigned cx,
  295.                         unsigned bx,
  296.                         unsigned ax,
  297.                         unsigned ip,
  298.                         unsigned cs,
  299.                         unsigned flags)
  300.     {
  301.     in_int16 = TRUE;
  302.     enable();
  303.     temp_ax = _AX;
  304.     temp_ah = _AH;
  305.  
  306.     if (temp_ax == 'PO')
  307.         {
  308.         ax = 'po';
  309.         es = FP_SEG( (void far *) mail_path);
  310.         bx = FP_OFF( (void far *) mail_path);
  311.         si = FP_OFF( (void far *) &outbasket_alarm);
  312.         di = FP_OFF( (void far *) &new_mail);
  313.         dx = FP_OFF( (void far *) &de_install);
  314.         goto int16_exit;
  315.         }
  316.  
  317.     if (temp_ah != 0)
  318.         goto do_old16;
  319.  
  320. wait_for_key:
  321.     _AH = 1;
  322.     oldint16();
  323.     asm     jz   check_flags
  324.  
  325.     goto do_old16;
  326.  
  327. check_flags:
  328.     if (in_popup)
  329.         oldint28();
  330.  
  331.     if (!mail_flag && !de_install)
  332.         goto wait_for_key;
  333.  
  334.     if (*indos_ptr != 0)
  335.          goto wait_for_key;
  336.  
  337.     if (*indos2_ptr != 0)
  338.          goto wait_for_key;
  339.  
  340.     outportb(0x20, 0x0b);
  341.     if (inportb(0x20)) goto wait_for_key;
  342.  
  343.     in_popup = TRUE;
  344.     process_mail();
  345.     in_popup = FALSE;
  346.  
  347.     goto wait_for_key;
  348.  
  349.  
  350. do_old16:
  351.     _AX = temp_ax;
  352.     oldint16();
  353.     asm     pushf
  354.     asm     pop flags
  355.     ax    = _AX;
  356.     bx    = _BX;
  357.     cx    = _CX;
  358.     dx    = _DX;
  359.  
  360. int16_exit:
  361.     in_int16 = FALSE;
  362.     }
  363.  
  364. void interrupt  int1b (void)
  365.     {
  366.     enable();
  367.     break_flag = TRUE;
  368.     }
  369.  
  370. void interrupt  int1c (void)
  371.     {
  372.     enable();
  373.     }
  374.  
  375. void interrupt  int23 (void)
  376.     {
  377.     enable();
  378.     }
  379.  
  380.  
  381. void    interrupt int24(unsigned bp,
  382.                         unsigned di,
  383.                         unsigned si,
  384.                         unsigned ds,
  385.                         unsigned es,
  386.                         unsigned dx,
  387.                         unsigned cx,
  388.                         unsigned bx,
  389.                         unsigned ax,
  390.                         unsigned ip,
  391.                         unsigned cs,
  392.                         unsigned flags)
  393.     {
  394.     temp1 = _AX;
  395.     critical_error = TRUE;
  396.  
  397.     if (_osmajor < 3)
  398.        ax = (temp1 & 0xFF00);
  399.     else
  400.        ax = (temp1 & 0xFF00) | 0x03;
  401.     }
  402.  
  403.  
  404. void    interrupt int28(void)
  405.     {
  406.     in_int28 = TRUE;
  407.     oldint28();
  408.     enable();
  409.  
  410.     if (!mail_flag && !de_install)
  411.         goto exit28;
  412.  
  413.     if (in_popup)
  414.         goto exit28;
  415.  
  416.     if (*indos_ptr > 1)
  417.          goto exit28;
  418.  
  419.     if (*indos2_ptr != 0)
  420.          goto exit28;
  421.  
  422.     outportb(0x20, 0x0b);
  423.     if (inportb(0x20))
  424.          goto exit28;
  425.  
  426.     in_popup = TRUE;
  427.     process_mail();
  428.     in_popup = FALSE;
  429.  
  430. exit28:
  431.     in_int28 = FALSE;
  432.     }
  433.  
  434. /* ------------------------------------------- */
  435.  
  436.  
  437. /* - - - - - - - - - - - - - - - - - - - - - - - */
  438. /*
  439.  *  A function to call NetBIOS (via Int 5C).
  440.  *
  441.  *
  442. */
  443. void    NetBios(NCB *ncb_ptr)
  444.         {
  445.         ncb_ptr->NCB_CMD_CPLT = 0xFF;
  446.  
  447.         _ES    = FP_SEG(ncb_ptr);
  448.         _BX    = FP_OFF(ncb_ptr);
  449.         _AX    = 0x0100;
  450.  
  451.         geninterrupt(0x5c);
  452.         }
  453.  
  454. /* - - - - - - - - - - - - - - - - - - - - - - - */
  455. /*
  456.  *  Expand 'name' to be a 16 byte string, padded
  457.  *  on the right with spaces, and null-terminated.
  458.  *  (Doesn't work with 'permanent node names'.)
  459. */
  460. void    expand_to_16_chars(char *name)
  461.         {
  462.         char *p;
  463.         char tmp[17];
  464.         int  i;
  465.  
  466.         memset(tmp, ' ', 15);
  467.         p = name;
  468.         i = 0;
  469.         while (i < 15 && *p)
  470.             {
  471.             tmp[i] = *p;
  472.             i++;
  473.             p++;
  474.             }
  475.         tmp[15] = '\0';
  476.         strcpy(name, tmp);
  477.         }
  478.  
  479. /* - - - - - - - - - - - - - - - - - - - - - - - */
  480. /*
  481.  *  Build the 'add_name' NCB and send it out
  482.  *  across the network.
  483.  *
  484. */
  485. void    net_add_name(char *name)
  486.         {
  487.         memset(&add_name_ncb, 0, sizeof(NCB));
  488.         add_name_ncb.NCB_COMMAND = ADD_NAME;
  489.         strcpy(add_name_ncb.NCB_NAME, name);
  490.         expand_to_16_chars(add_name_ncb.NCB_NAME);
  491.         NetBios(&add_name_ncb);
  492.         }
  493.  
  494. /* - - - - - - - - - - - - - - - - - - - - - - - */
  495. /*
  496.  *    Build the 'delete_name' NCB
  497.  *
  498. */
  499. void    net_delete_name(char *name)
  500.         {
  501.         memset(&delete_name_ncb, 0, sizeof(NCB));
  502.         delete_name_ncb.NCB_COMMAND = DELETE_NAME;
  503.         strcpy(delete_name_ncb.NCB_NAME, name);
  504.         expand_to_16_chars(delete_name_ncb.NCB_NAME);
  505.         NetBios(&delete_name_ncb);
  506.         }
  507.  
  508.  
  509. /* - - - - - - - - - - - - - - - - - - - - - - - */
  510. /*
  511.  *    Build the 'cancel' NCB and send it out
  512.  *    across the network.
  513.  *
  514. */
  515. void    net_cancel(NCB *np)
  516.         {
  517.         memset(&cancel_ncb, 0, sizeof(NCB));
  518.         cancel_ncb.NCB_COMMAND = CANCEL;
  519.         cancel_ncb.NCB_BUFFER_PTR = np;
  520.         NetBios(&cancel_ncb);
  521.         }
  522.  
  523. /* - - - - - - - - - - - - - - - - - - - - - - - */
  524. /*
  525.  *    Build the 'receive datagram' NCB and send it out
  526.  *    across the network.  When the operation completes,
  527.  *    let NetBIOS call the POST routine to handle it.
  528. */
  529. void    net_receive_dg_post(unsigned char name_num,
  530.                          void interrupt (*post_function)(),
  531.                          void *packet_ptr, int packet_len)
  532.         {
  533.         memset(&receive_dg_ncb, 0, sizeof(NCB));
  534.         receive_dg_ncb.NCB_COMMAND = RECEIVE_DATAGRAM;
  535.         receive_dg_ncb.NCB_NUM = name_num;
  536.         receive_dg_ncb.NCB_LENGTH = packet_len;
  537.         receive_dg_ncb.NCB_BUFFER_PTR = packet_ptr;
  538.         receive_dg_ncb.POST_FUNC = post_function;
  539.         NetBios(&receive_dg_ncb);
  540.         }
  541.  
  542. /* - - - - - - - - - - - - - - - - - - - - - - - */
  543. /*
  544.  *    Build the 'send datagram' NCB and send it out
  545.  *    across the network.
  546.  *
  547. */
  548. void    net_send_dg(char *destination,
  549.                     unsigned char name_num, 
  550.                     void *packet_ptr, 
  551.                     int packet_len)
  552.         {
  553.         memset(&send_dg_ncb, 0, sizeof(NCB));
  554.         send_dg_ncb.NCB_COMMAND = SEND_DATAGRAM;
  555.         send_dg_ncb.NCB_NUM = name_num;
  556.         strcpy(send_dg_ncb.NCB_CALLNAME, destination);
  557.         expand_to_16_chars(send_dg_ncb.NCB_CALLNAME);
  558.         send_dg_ncb.NCB_LENGTH = packet_len;
  559.         send_dg_ncb.NCB_BUFFER_PTR = packet_ptr;
  560.         NetBios(&send_dg_ncb);
  561.         }
  562.  
  563. /* - - - - - - - - - - - - - - - - - - - - - - - */
  564.  
  565. int     okay_to_unload(void)
  566.         {
  567.         next_mcb       = MK_FP( (ourpsp) + *our_mcb_size, 0);
  568.         next_mcb_owner = MK_FP(  ourpsp  + *our_mcb_size, 1);
  569.  
  570.         if (  *next_mcb_owner == 0x0000
  571.            || *next_mcb_owner == 0xffff
  572.            || *next_mcb_owner <  ourpsp  )
  573.                 return TRUE;
  574.  
  575.         return FALSE;
  576.         }
  577.  
  578. void    beep(void)
  579.         {
  580.         sound(880);
  581.         delay(100);
  582.         nosound();
  583.         }
  584.  
  585. /* ----------------------------------------------- */
  586.  
  587. void    announce_mail(void)
  588.         {
  589.         char    linsav[160];
  590.         int     n, cpos, ctype, vid_mode;
  591.  
  592.         _AH = 15;
  593.         geninterrupt(0x10);
  594.         _AH = 0;
  595.         vid_mode = _AX;
  596.         if (vid_mode != 2
  597.             && vid_mode != 3
  598.             && vid_mode != 7)
  599.                 {
  600.                 beep();
  601.                 delay(100);
  602.                 beep();
  603.                 delay(10);
  604.                 beep();
  605.                 return;
  606.                 }
  607.  
  608.         gettext(1, 25, 80, 25, linsav);
  609.         _AH = 3;
  610.         _BH = 0;
  611.         geninterrupt(0x10);
  612.         cpos  = _DX;
  613.         ctype = _CX;
  614.  
  615.         gotoxy(1, 25);
  616.         textcolor(BLACK);
  617.         textbackground(LIGHTGRAY);
  618.         cprintf("%-79.79s", "                     You have mail.");
  619.         beep();
  620.  
  621.         for (n=0; n<20; n++)
  622.             {
  623.             delay(100);
  624.             if (bioskey(1))
  625.                 {
  626.                 bioskey(0);
  627.                 break;
  628.                 }
  629.             }
  630.  
  631.         puttext(1, 25, 80, 25, linsav);
  632.         _DX = cpos;
  633.         _AH = 2;
  634.         _BH = 0;
  635.         geninterrupt(0x10);
  636.         _CX = ctype;
  637.         _AH = 1;
  638.         geninterrupt(0x10);
  639.         }
  640.  
  641. void    send_ack(void)
  642.         {
  643.         packet_in.type = ACK;
  644.         packet_in.data_length = 0;
  645.         net_send_dg(caller, name_number, &packet_in, 5);
  646.         }
  647.  
  648. void    receive_incoming_mail(void)
  649.         {
  650.         long t;
  651.         char filepart[10];
  652.         char extpart[6];
  653.  
  654.         incoming_alarm = tick_counter + 1092l;
  655.  
  656.         switch (packet_in.type)
  657.             {
  658.             case HEADER :
  659.                 {
  660.                 strcpy(caller, receive_dg_ncb.NCB_CALLNAME);
  661.                 state = 1;
  662.                 first_packet = TRUE;
  663.                 time(&t);
  664.                 sprintf(string, "%ld", t);
  665.                 strcpy(mailname, mail_path);
  666.                 strcat(mailname, &string[3]);
  667.                 strcat(mailname, ".IN");
  668.                 mail_handle = _creat(mailname, 0);
  669.                 if (mail_handle == -1)
  670.                     return;
  671.                 send_ack();
  672.                 break;
  673.                 }
  674.             case MAIL_DATA :
  675.                 {
  676.                 write(mail_handle, packet_in.data,
  677.                         packet_in.data_length);
  678.                 if (first_packet)
  679.                     {
  680.                     memcpy(&envelope_in,
  681.                            &packet_in.data, sizeof(ENVELOPE));
  682.                     first_packet = FALSE;
  683.                     }
  684.                 send_ack();
  685.                 break;
  686.                 }
  687.             case MAIL_EOF :
  688.                 {
  689.                 close(mail_handle);
  690.                 mail_handle = -1;
  691.                 send_ack();
  692.                 break;
  693.                 }
  694.             case FILE_HDR :
  695.                 {
  696.                 fnsplit(envelope_in.attachment_name,
  697.                         NULL, NULL, filepart, extpart);
  698.                 strcpy(filename, mail_path);
  699.                 strcat(filename, filepart);
  700.                 strcat(filename, extpart);
  701.                 file_handle = _creat(filename, 0);
  702.                 if (file_handle != -1)
  703.                     send_ack();
  704.                 break;
  705.                 }
  706.             case FILE_DATA :
  707.                 {
  708.                 write(file_handle, packet_in.data,
  709.                         packet_in.data_length);
  710.                 send_ack();
  711.                 break;
  712.                 }
  713.             case FILE_EOF :
  714.                 {
  715.                 close(file_handle);
  716.                 file_handle = -1;
  717.                 send_ack();
  718.                 break;
  719.                 }
  720.             case TRAILER :
  721.                 {
  722.                 new_mail = TRUE;
  723.                 incoming_alarm = 0x0FFFFFFFl;
  724.                 state = 0;
  725.                 expected_sequence = 0;
  726.                 send_ack();
  727.                 announce_mail();
  728.                 break;
  729.                 }
  730.             default :
  731.                 {
  732.                 return;
  733.                 }
  734.             };
  735.  
  736.         expected_sequence++;
  737.         }
  738.  
  739. void    cancel_incoming_mail(void)
  740.         {
  741.         if (mail_handle != -1)
  742.             {
  743.             close(mail_handle);
  744.             unlink(mailname);
  745.             mail_handle = -1;
  746.             }
  747.         if (file_handle != -1)
  748.             {
  749.             close(file_handle);
  750.             unlink(filename);
  751.             file_handle = -1;
  752.             }
  753.         state = 0;
  754.         expected_sequence = 1;
  755.         }
  756.  
  757. void    send_next_packet(void)
  758.         {
  759.         int rc, retry_count;
  760.  
  761.         no_answer_alarm = tick_counter + 91l;
  762.         errors_this_packet = 0;
  763.         packet_out.sequence++;
  764.  
  765.         if (packet_out.type == TRAILER)
  766.             {
  767.             packet_out.type = HEADER;
  768.             send_mail(0);
  769.             return;
  770.             }
  771.  
  772.         if (packet_out.type == FILE_EOF)
  773.             {
  774.             retry_count = 0;
  775.             do  rc = unlink(outname);
  776.                 while (rc != 0 && ++retry_count < 10);
  777.             packet_out.type = TRAILER;
  778.             net_send_dg(addressee, name_number, &packet_out, 5);
  779.             return;
  780.             }
  781.  
  782.         if (packet_out.type == MAIL_EOF)
  783.             {
  784.             if (envelope_out.attachment_flag == 'N'
  785.                 || strcmp(envelope_out.addressee, 
  786.                         envelope_out.sender) == 0)
  787.                 {
  788.                 retry_count = 0;
  789.                 do  rc = unlink(outname);
  790.                     while (rc != 0 && ++retry_count < 10);
  791.                 packet_out.type = TRAILER;
  792.                 net_send_dg(addressee, name_number, &packet_out, 5);
  793.                 return;
  794.                 }
  795.             send_handle = 
  796.                     open(envelope_out.attachment_name,
  797.                     O_RDWR | O_DENYALL);
  798.             if (send_handle == -1)
  799.                 {
  800.                 retry_count = 0;
  801.                 do  rc = unlink(outname);
  802.                     while (rc != 0 && ++retry_count < 10);
  803.                 packet_out.type = TRAILER;
  804.                 net_send_dg(addressee, name_number, &packet_out, 5);
  805.                 return;
  806.                 }
  807.             packet_out.type = FILE_HDR;
  808.             packet_out.data_length = 0;
  809.             net_send_dg(addressee, name_number, &packet_out, 5);
  810.             return;
  811.             }
  812.  
  813.         if (packet_out.type == FILE_DATA
  814.             || packet_out.type == FILE_HDR)
  815.             {
  816.             packet_out.type = FILE_DATA;
  817.             packet_out.data_length 
  818.                 = read(send_handle, packet_out.data, 500);
  819.             if (packet_out.data_length == 0)
  820.                 {
  821.                 close(send_handle);
  822.                 send_handle = -1;
  823.                 packet_out.type = FILE_EOF;
  824.                 }
  825.             net_send_dg(addressee, name_number,
  826.                         &packet_out, packet_out.data_length+5);
  827.             return;
  828.             }
  829.  
  830.         if (packet_out.type == HEADER)
  831.             {
  832.             send_handle = open(outname, O_RDWR | O_DENYALL);
  833.             if (send_handle == -1)
  834.                 return;
  835.             }
  836.  
  837.         packet_out.type = MAIL_DATA;
  838.         packet_out.data_length 
  839.             = read(send_handle, packet_out.data, 500);
  840.         if (packet_out.data_length == 0)
  841.             {
  842.             close(send_handle);
  843.             send_handle = -1;
  844.             packet_out.type = MAIL_EOF;
  845.             }
  846.  
  847.         net_send_dg(addressee, name_number,
  848.                     &packet_out, packet_out.data_length+5);
  849.         }
  850.  
  851. void    send_mail(int first_item)
  852.         {
  853.         int i, flag;
  854.  
  855.         if (!first_item && packet_out.type != HEADER)
  856.             {
  857.             if (++errors_this_packet < 10)
  858.                 {
  859.                 outbasket_alarm = tick_counter + 10920l;
  860.                 no_answer_alarm = tick_counter + 91l;
  861.                 net_send_dg(addressee, name_number, 
  862.                             &packet_out, packet_out.data_length+5);
  863.                 return;
  864.                 }
  865.             if (send_handle != -1)
  866.                 close(send_handle);
  867.             }
  868.  
  869.         if (first_item)
  870.             {
  871.             strcpy(outname, mail_path);
  872.             strcat(outname, "*.out");
  873.             flag = findfirst(outname, &find_block, 0);
  874.             }
  875.         else
  876.             flag = findnext(&find_block);
  877.  
  878.         if (flag != 0)
  879.             {
  880.             no_answer_alarm = 0x0FFFFFFFl;
  881.             return;
  882.             }
  883.  
  884.         outbasket_alarm = tick_counter + 10920l;
  885.         no_answer_alarm = tick_counter + 91l;
  886.         errors_this_packet = 0;
  887.  
  888.         packet_out.type = HEADER;
  889.         packet_out.sequence = 1;
  890.         packet_out.data_length = 0;
  891.  
  892.         strcpy(outname, mail_path);
  893.         strcat(outname, find_block.ff_name);
  894.         send_handle = open(outname, O_RDWR | O_DENYALL);
  895.         if (send_handle == -1)
  896.             return;
  897.         i = read(send_handle, &envelope_out, sizeof(ENVELOPE));
  898.         close(send_handle);
  899.         send_handle = -1;
  900.         if (i != sizeof(ENVELOPE))
  901.             return;
  902.         strcpy(addressee, envelope_out.addressee);
  903.         strupr(addressee);
  904.         net_send_dg(addressee, name_number, &packet_out, 5);
  905.         }
  906.  
  907. void    post_office(void)
  908.         {
  909.         mail_flag = FALSE;
  910.  
  911.         if (incoming_msg)
  912.             {
  913.             incoming_msg = FALSE;
  914.             if (receive_dg_ncb.NCB_CMD_CPLT != 0)
  915.                 {
  916.                 gotoxy(50, 1);
  917.                 cprintf("Mail error!  code = %d.",
  918.                     (int) receive_dg_ncb.NCB_CMD_CPLT);
  919.                 gotoxy(1,1);
  920.                 cancel_incoming_mail();
  921.                 net_receive_dg_post(name_number,
  922.                                     POST_routine,
  923.                                     &packet_in,
  924.                                     sizeof(MAIL_PACKET));
  925.                 }
  926.             else
  927.             if (packet_in.type == ACK)
  928.                 {
  929.                 send_next_packet();
  930.                 net_receive_dg_post(name_number,
  931.                                     POST_routine,
  932.                                     &packet_in,
  933.                                     sizeof(MAIL_PACKET));
  934.                 }
  935.             else
  936.             if (packet_in.type == HEADER && state != 0)
  937.                 {
  938.                 net_receive_dg_post(name_number,
  939.                                     POST_routine,
  940.                                     &packet_in,
  941.                                     sizeof(MAIL_PACKET));
  942.                 }
  943.             else
  944.             if (packet_in.sequence == expected_sequence)
  945.                 {
  946.                 receive_incoming_mail();
  947.                 net_receive_dg_post(name_number,
  948.                                     POST_routine,
  949.                                     &packet_in,
  950.                                     sizeof(MAIL_PACKET));
  951.                 }
  952.             else
  953.             if (packet_in.sequence == expected_sequence - 1)
  954.                 {
  955.                 send_ack();
  956.                 net_receive_dg_post(name_number,
  957.                                     POST_routine,
  958.                                     &packet_in,
  959.                                     sizeof(MAIL_PACKET));
  960.                 }
  961.             else
  962.                 {
  963.                 cancel_incoming_mail();
  964.                 net_receive_dg_post(name_number,
  965.                                     POST_routine,
  966.                                     &packet_in,
  967.                                     sizeof(MAIL_PACKET));
  968.                 }
  969.             goto post_office_exit;
  970.             }
  971.  
  972.         if (incoming_timeout)
  973.             {
  974.             incoming_timeout = FALSE;
  975.             incoming_alarm   = 0x0FFFFFFFl;
  976.             cancel_incoming_mail();
  977.             goto post_office_exit;
  978.             }
  979.  
  980.         if (no_answer)
  981.             {
  982.             no_answer = FALSE;
  983.             send_mail(0);
  984.             }
  985.  
  986.         if (trigger_outbasket)
  987.             {
  988.             trigger_outbasket = FALSE;
  989.             outbasket_alarm   = tick_counter + 10920l;
  990.             send_mail(1);
  991.             }
  992.  
  993. post_office_exit:
  994.         ;
  995.         }
  996.  
  997. void    process_mail(void)
  998.         {
  999.         disable();
  1000.         old_ss = _SS;
  1001.         old_sp = _SP;
  1002.         _SS = our_ss;
  1003.         _SP = our_sp;
  1004.         enable();
  1005.  
  1006.         if (de_install)
  1007.             {
  1008.             if (!okay_to_unload())
  1009.                 goto process_mail_exit;
  1010.             _AX = 0x5000;
  1011.             _BX = ourpsp;
  1012.             geninterrupt(0x21);
  1013.             setvect(0x08, oldint08);
  1014.             setvect(0x28, oldint28);
  1015.             setvect(0x09, oldint09);
  1016.             setvect(0x10, oldint10);
  1017.             setvect(0x13, oldint13);
  1018.             setvect(0x16, oldint16);
  1019.             net_cancel(&receive_dg_ncb);
  1020.             net_delete_name(mail_name);
  1021.             _ES = ourpsp;
  1022.             _BX = 0x2c;
  1023.             asm   mov es, es:[bx]
  1024.             _AH = 0x49;
  1025.             geninterrupt(0x21);
  1026.             _ES = ourpsp;
  1027.             _AH = 0x49;
  1028.             geninterrupt(0x21);
  1029.             asm   mov ax, word ptr next_mcb+2
  1030.             asm   inc ax
  1031.             asm   mov es, ax
  1032.             _AH = 0x49;
  1033.             geninterrupt(0x21);
  1034.             _AX = 0x4c00;
  1035.             geninterrupt(0x21);
  1036.             }
  1037.  
  1038.         break_state = getcbrk();
  1039.         oldint1b = getvect(0x1b);
  1040.         setvect(0x1b, int1b);
  1041.         oldint1c = getvect(0x1c);
  1042.         setvect(0x1c, int1c);
  1043.         oldint23 = getvect(0x23);
  1044.         setvect(0x23, int23);
  1045.         oldint24 = getvect(0x24);
  1046.         setvect(0x24, int24);
  1047.         olddta_ptr = getdta();
  1048.         setdta(ourdta_ptr);
  1049.         _AX = 0x5100;
  1050.         geninterrupt(0x21);
  1051.         oldpsp = _BX;
  1052.         _AX = 0x5000;
  1053.         _BX = ourpsp;
  1054.         geninterrupt(0x21);
  1055.  
  1056.         post_office();
  1057.  
  1058.         _AX = 0x5000;
  1059.         _BX = oldpsp;
  1060.         geninterrupt(0x21);
  1061.         setdta(olddta_ptr);
  1062.         setvect(0x24, oldint24);
  1063.         setvect(0x23, oldint23);
  1064.         setvect(0x1c, oldint1c);
  1065.         setvect(0x1b, oldint1b);
  1066.         setcbrk(break_state);
  1067.  
  1068. process_mail_exit:
  1069.         disable();
  1070.         _SS = old_ss;
  1071.         _SP = old_sp;
  1072.         enable();
  1073.         }
  1074.  
  1075. void    interrupt POST_routine(void)
  1076.         {
  1077.         incoming_msg = TRUE;
  1078.         mail_flag   = TRUE;
  1079.         }
  1080.  
  1081. /* ------------------------------------------- */
  1082.  
  1083. void    main(int argc, char *argv[])
  1084.         {
  1085.         _fmode = O_BINARY;
  1086.  
  1087.         if (_osmajor < 2)
  1088.             {
  1089.             cprintf("\r\n");
  1090.             cprintf("Early versions of DOS not supported...\r\n");
  1091.             exit(1);
  1092.             }
  1093.  
  1094.         _AX = 'PO';
  1095.         geninterrupt(0x16);
  1096.         if (_AX == 'po')
  1097.             {
  1098.             cprintf("\r\n");
  1099.             cprintf("The PostMan program was already loaded.\r\n");
  1100.             exit(1);
  1101.             }
  1102.  
  1103.         if ( (our_stack = malloc(1000)) == NULL)
  1104.             {
  1105.             cprintf("\r\n");
  1106.             cprintf("Insufficient memory...\r\n");
  1107.             exit(1);
  1108.             }
  1109.  
  1110.         getcwd(mail_path, 64);
  1111.         if (mail_path[strlen(mail_path) - 1] != '\\')
  1112.             strcat(mail_path, "\\");
  1113.  
  1114.         our_ss    = _DS;
  1115.         our_sp    = FP_OFF( (void far *) our_stack) + 998;
  1116.  
  1117.         _AX = 0x3400;
  1118.         geninterrupt(0x21);
  1119.         temp2 = _BX;
  1120.         temp1 = _ES;
  1121.         indos_ptr = MK_FP(temp1, temp2);
  1122.         if (_osmajor == 2)
  1123.             indos2_ptr = MK_FP(temp1, temp2 + 1);
  1124.         else
  1125.             indos2_ptr = MK_FP(temp1, temp2 - 1);
  1126.  
  1127.         delay(10);
  1128.         kbd_flag_ptr   = MK_FP(0x0040, 0x0017);
  1129.  
  1130.         _DX = FP_OFF( (void far *) machine_name);
  1131.         _AX = 0x5E00;
  1132.         geninterrupt(0x21);
  1133.         if (_CH == 0)
  1134.             {
  1135.             printf("ERROR.  Machine name not set.\n");
  1136.             exit(1);
  1137.             }
  1138.         machine_name[14] = '\0';
  1139.         strupr(machine_name);
  1140.         strcpy(mail_name, "!");
  1141.         strcat(mail_name, machine_name);
  1142.  
  1143.         i = strlen(machine_name) - 1;
  1144.         while (i > 0 && machine_name[i] == ' ')
  1145.             {
  1146.             machine_name[i] = '\0';
  1147.             i--;
  1148.             }
  1149.  
  1150.         int_5C_vector = getvect(0x5C);
  1151.         if (int_5C_vector == NULL)
  1152.             {
  1153.             printf("ERROR. NetBios not loaded (Int5C not present).\n");
  1154.             exit(1);
  1155.             }
  1156.  
  1157.         memset(&temp_ncb, 0, sizeof(NCB));
  1158.         temp_ncb.NCB_COMMAND = 0x7F;
  1159.         NetBios(&temp_ncb);
  1160.         if (temp_ncb.NCB_RETCODE != 03)
  1161.             {
  1162.             printf("ERROR. NetBios not loaded (No response from Int5C).\n");
  1163.             exit(1);
  1164.             }
  1165.  
  1166.         printf("Adding mailing address (%s) to the network...", machine_name);
  1167.         net_add_name(mail_name);
  1168.         while (add_name_ncb.NCB_CMD_CPLT == 0xFF)
  1169.             ;
  1170.         printf("\n");
  1171.         if (add_name_ncb.NCB_CMD_CPLT != 0)
  1172.             {
  1173.             printf("ERROR.  NetBios said: %s.\n",
  1174.                 net_error_message[(int)add_name_ncb.NCB_CMD_CPLT]);
  1175.             exit(1);
  1176.             }
  1177.  
  1178.         name_number = add_name_ncb.NCB_NUM;
  1179.         cprintf("\r\n\r\n");
  1180.         cprintf("PostMan is loaded.\r\n");
  1181.         cprintf("Run the 'MAIL' program to see your IN/OUT baskets.\r\n");
  1182.  
  1183.         ourdta_ptr = getdta();
  1184.         _AX = 0x5100;
  1185.         geninterrupt(0x21);
  1186.         ourpsp = _BX;
  1187.         our_mcb       = MK_FP(ourpsp-1, 0);
  1188.         our_mcb_size  = MK_FP(ourpsp-1, 3);
  1189.         oldint08 = getvect(0x08);
  1190.         oldint09 = getvect(0x09);
  1191.         oldint10 = getvect(0x10);
  1192.         oldint13 = getvect(0x13);
  1193.         oldint16 = getvect(0x16);
  1194.         oldint28 = getvect(0x28);
  1195.  
  1196.         asm     mov ax, word ptr oldint10
  1197.         asm     mov word ptr cs:[0000h], ax
  1198.         asm     mov ax, word ptr oldint10+2
  1199.         asm     mov word ptr cs:[0002h], ax
  1200.         asm     mov ax, word ptr oldint13
  1201.         asm     mov word ptr cs:[0004h], ax
  1202.         asm     mov ax, word ptr oldint13+2
  1203.         asm     mov word ptr cs:[0006h], ax
  1204.  
  1205.         setvect(0x10, (void interrupt (*)()) int10);
  1206.         setvect(0x13, (void interrupt (*)()) int13);
  1207.         setvect(0x16, int16);
  1208.         setvect(0x09, int09);
  1209.         setvect(0x28, int28);
  1210.         setvect(0x08, int08);
  1211.  
  1212.         net_receive_dg_post(name_number,
  1213.                             POST_routine,
  1214.                             &packet_in,
  1215.                             sizeof(MAIL_PACKET));
  1216.  
  1217.         paragraphs = (our_ss + (our_sp >> 4) + 1) - ourpsp;
  1218.         keep(0, paragraphs);
  1219.         }
  1220.  
  1221.  
  1222.